home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / gsdb25.zip / GS_EDIT.PAS < prev    next >
Pascal/Delphi Source File  |  1991-07-07  |  23KB  |  766 lines

  1. Unit GS_Edit;
  2. {-----------------------------------------------------------------------------
  3.                                  Editor Routines
  4.  
  5.        GS_Edit Copyright (c)  Richard F. Griffin
  6.  
  7.        10 January 1991
  8.  
  9.        102 Molded Stone Pl
  10.        Warner Robins, GA  31088
  11.  
  12.        -------------------------------------------------------------
  13.        This unit handles the objects for a simple editor similar to
  14.        WordStar.
  15.  
  16.        Changes:
  17.  
  18.        18 May 91 - Modified Presssed_Del to bring up the succeeding line
  19.                    if the cursor is at the end of the line.
  20.  
  21.        06 Jun 91 - Modified startup routine to initialize the windows.  all
  22.                    All instances will use the same window object.
  23.  
  24. ------------------------------------------------------------------------------}
  25.  
  26.  
  27.  
  28.  
  29.  
  30. interface
  31. uses
  32.    CRT,
  33.    Dos,
  34.    GS_KeyI,
  35.    GS_Scrn,
  36.    GS_Winfc,
  37.    GS_Error,
  38.    GS_Strng;
  39. type
  40.    GS_Edit_Pntr = ^GS_Edit_Line;
  41.    GS_Edit_Line = record
  42.                      Next_Line,
  43.                      Prev_Line  : GS_Edit_Pntr;
  44.                      Return_Cod : byte;
  45.                      Line_Size  : integer;
  46.                      Valu_Line  : string;
  47.                   end;
  48.  
  49.    GS_Edit_Blok = record
  50.                      Blok_Line,
  51.                      Blok_Colm  : integer;
  52.                   end;
  53.  
  54.    GS_Edit_Objt = object
  55.                      First_Line,
  56.                      End_Line,
  57.                      Work_Line   : GS_Edit_Pntr;
  58.                                       {Used to track lines}
  59.                      Cursor_LocX,
  60.                      Cursor_LocY : word;
  61.                                       {Hold cursor location}
  62.                      Active_Line,     {Current line number}
  63.                      Total_Lines,     {Total number of lines}
  64.                      Screen_Top,      {Line number at top of screen}
  65.                      Screen_Btm  : longint;
  66.                                       {Line Number at bottom of screen}
  67.                      CursorPos   : integer;
  68.                                       {Position in line}
  69.                      CursorLine  : integer;
  70.                                       {Line currently working on}
  71.                      Temp_Line   : string;
  72.                                       {work area during wordwrap}
  73.                      Edit_Lgth   : integer;
  74.                                       {Max size of eaach line}
  75.                      Lines_Avail : integer;
  76.                                       {Number of lines that will fit in the}
  77.                                       {window on the screen}
  78.                      Ch_Work     : char;
  79.                                       {Hold area for keystrokes}
  80.                      Word_Wrap   : boolean;
  81.                                       {True sets word wrap on}
  82.                      WW_Flag     : boolean;
  83.                                       {Internal flag for wordwrap condition}
  84.                      Blok_Begin,
  85.                      Blok_Fini   : GS_Edit_Blok;
  86.                                       {Future use for block operations}
  87.  
  88.  
  89.                      function    Byte_Count : longint;
  90.                      procedure   Check_Func_Keys;
  91.                      procedure   Clear_Editor;
  92.                      procedure   Edit;
  93.                      Procedure   Edit_Line;
  94.                      function    Find_Line(linenum : integer) : boolean;
  95.                      function    Get_Line_Mem(lth : integer) : pointer;
  96.                      constructor Init;
  97.                      Procedure   Rel_Line_Mem(linenum : integer);
  98.                      Procedure   Show_Lines(b, e :integer);
  99.                      Procedure   View;
  100.                      Procedure   WordWrap(Fline : string);
  101.                      Procedure   Pressed_Bsp;
  102.                      Procedure   Pressed_CrtlY;
  103.                      Procedure   Pressed_Del;
  104.                      Procedure   Pressed_DnAr;
  105.                      Procedure   Pressed_F1;
  106.                      Procedure   Pressed_Ret;
  107.                      Procedure   Pressed_UpAr;
  108.                      Procedure   Pressed_PgUp;
  109.                      Procedure   Pressed_PgDn;
  110.                   end;
  111.  
  112.  
  113. implementation
  114. var
  115.    StatWin,
  116.    HelpWin,
  117.    EditWin  : GS_Wind_Objt;
  118.  
  119. function GS_Edit_Objt.Byte_Count : longint;
  120. var
  121.    i : longint;
  122.    p : GS_Edit_Pntr;
  123. begin
  124.    i := 0;
  125.    p := First_Line;
  126.    while (p <> nil) do
  127.    begin
  128.       i := i + length(p^.Valu_Line) + 2;
  129.                                       {Add length of line + CR/LF chars}
  130.       p := p^.Next_Line;
  131.    end;
  132.    inc(i);                            {Add one for EOF byte}
  133.    Byte_Count := i;
  134. end;
  135.  
  136. procedure GS_Edit_Objt.Clear_Editor;
  137. begin
  138.    Work_Line := First_Line;
  139.    while (Work_Line <> nil) do
  140.    begin
  141.       End_Line := Work_Line^.Next_Line;
  142.       FreeMem(Work_Line,Work_Line^.Line_Size);
  143.       Work_Line := End_Line;
  144.    end;
  145.    First_Line := nil;
  146.    End_Line := nil;
  147.    Work_Line := nil;
  148.    Active_line := 0;
  149.    Total_Lines := 0;
  150. end;
  151.  
  152.  
  153. constructor GS_Edit_Objt.Init;
  154. begin
  155.    First_Line := nil;
  156.    End_Line := nil;
  157.    Work_Line := nil;
  158.    Word_Wrap := true;
  159.    WW_Flag := false;
  160.    Active_Line := 0;
  161.    Total_Lines := 0;
  162.    Screen_Top := 0;
  163.    Screen_Btm := 0;
  164.    Ch_Work := #0;
  165.    CursorPos := 1;
  166.    CursorLine := 1;
  167.    Temp_Line := '';
  168.    GS_KeyI_Ins := True;               {Start in insert mode}
  169.    Edit_Lgth := 32;
  170. end;
  171.  
  172.  
  173. procedure GS_Edit_Objt.Pressed_F1;
  174. var
  175.    cc : char;
  176. begin
  177.    HelpWin.SetWin;
  178.    writeln('Toggle Ins  - Ins');
  179.    writeln('Delete Char - Del');
  180.    writeln('Delete Line - Ctl-Y');
  181.    writeln('Press any Key');
  182.    cc := ReadKey;
  183.    if cc = #0 then cc := ReadKey;
  184.    HelpWin.RelWin;
  185. end;
  186.  
  187.  
  188. procedure GS_Edit_Objt.Pressed_Bsp;
  189. var
  190.    bb : byte;
  191.    ss : string;
  192.    ll : boolean;
  193. begin
  194.    if CursorPos > 1 then
  195.    begin
  196.       Delete(Work_Line^.Valu_Line, Pred(CursorPos), 1);
  197.       GoToXY(1, CursorLine);
  198.       Write(Work_Line^.Valu_Line);
  199.       ClrEol;
  200.       Dec(CursorPos);
  201.    end
  202.    else
  203.    begin
  204.       if Active_Line > 1 then
  205.       begin
  206.          bb := Work_line^.Return_Cod;
  207.          ss := Work_Line^.Valu_Line;
  208.          if Active_Line < Total_Lines then
  209.          begin
  210.             Pressed_CrtlY;
  211.             Pressed_UpAr;
  212.          end else Pressed_CrtlY;
  213.          Work_Line^.Return_Cod := bb;
  214.          ss := Work_Line^.Valu_Line + ss;
  215.          CursorPos := length(Work_Line^.Valu_Line);
  216.          WordWrap(ss);
  217.          GotoXY(1,succ(Active_Line-Screen_Top));
  218.          write(Work_Line^.Valu_Line);
  219.       end;
  220.    end;
  221. end;
  222.  
  223. procedure GS_Edit_Objt.Pressed_Del;
  224. begin
  225.    if CursorPos <= Length(Work_Line^.Valu_Line) then
  226.    begin
  227.       Delete(Work_Line^.Valu_Line, CursorPos, 1);
  228.       GoToXY(1, CursorLine);
  229.       Write(Work_Line^.Valu_Line);
  230.       ClrEol;
  231.    end
  232.    else
  233.    begin
  234.       if Active_Line < Total_Lines then
  235.       begin
  236.          Pressed_DnAr;
  237.          CursorPos := 1;
  238.          Pressed_Bsp;
  239.       end;
  240.    end;
  241. end;
  242.  
  243. procedure GS_Edit_Objt.Pressed_PgDn;
  244. begin         {Page Down}
  245.    Active_Line := pred(Screen_Top + Lines_Avail);
  246.    if Active_Line > Total_Lines then Active_Line := Total_Lines;
  247.    if not Find_Line(Active_Line) then
  248.    begin
  249.       ShowError(710,'Pressed_PgDn');
  250.       exit;
  251.    end;
  252.    if Active_Line <> Screen_Top then Show_Lines(Active_Line,Total_Lines);
  253.    CursorLine := 1;
  254.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  255.       CursorPos := length(Work_Line^.Valu_Line)+1;
  256. end;
  257.  
  258. procedure GS_Edit_Objt.Pressed_PgUp;
  259. begin         {Page Up}
  260.    if Active_Line <= 1 then exit;
  261.    Active_Line := succ(Screen_Top - Lines_Avail);
  262.    if Active_Line < 1 then Active_Line := 1;
  263.    if not Find_Line(Active_Line) then
  264.    begin
  265.       ShowError(710,'Pressed_PgUp');
  266.       exit;
  267.    end;
  268.    if Active_Line < Screen_Top then Show_Lines(Active_Line,Total_Lines);
  269.    CursorLine := 1;
  270.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  271.       CursorPos := length(Work_Line^.Valu_Line)+1;
  272. end;
  273.  
  274. procedure GS_Edit_Objt.Pressed_UpAr;
  275. begin         {Up Arrow}
  276.    if Active_Line <= 1 then exit;
  277.    if not Find_Line(pred(Active_Line)) then
  278.    begin
  279.       ShowError(710,'Pressed_UpAr');
  280.       exit;
  281.    end;
  282.    if Active_Line < Screen_Top then
  283.    begin
  284.       gotoxy(1,1);
  285.       InsLine;
  286.       dec(Screen_Top);
  287.       write(Work_Line^.Valu_Line);
  288.    end;
  289.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  290.       CursorPos := length(Work_Line^.Valu_Line)+1;
  291. end;
  292.  
  293. procedure GS_Edit_Objt.Pressed_DnAr;
  294. begin         {Down Arrow}
  295.    if Active_Line >= Total_Lines then exit;
  296.    if not Find_Line(succ(Active_Line)) then
  297.    begin
  298.       ShowError(710,'Pressed_DnAr');
  299.       exit;
  300.    end;
  301.    if Active_Line-Screen_Top >= Lines_Avail then
  302.    begin
  303.       GoToXY(1,1);
  304.       DelLine;
  305.       inc(Screen_Top);
  306.       GotoXY(1,Lines_Avail);
  307.       write(Work_Line^.Valu_Line);
  308.    end;
  309.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  310.    CursorPos := length(Work_Line^.Valu_Line)+1;
  311. end;
  312.  
  313.  
  314. procedure GS_Edit_Objt.Pressed_Ret;
  315. begin         {Return}
  316.    GS_KeyI_Ret := true;
  317.    Work_Line^.Return_Cod := $0D;
  318.    if GS_KeyI_Ins then
  319.    begin
  320.       ClrEol;
  321.       Temp_Line := Work_Line^.Valu_Line;
  322.       Work_Line^.Valu_Line := substr(Work_Line^.Valu_Line,1,pred(CursorPos));
  323.       delete(Temp_Line,1,pred(CursorPos));
  324.       Work_Line := Get_Line_Mem(Edit_Lgth);
  325.       Work_Line^.Valu_Line  := Temp_Line;
  326.       if Active_Line-Screen_Top >= Lines_Avail then
  327.       begin
  328.          GoToXY(1,1);
  329.          DelLine;
  330.          inc(Screen_Top);
  331.          GotoXY(1,Lines_Avail);
  332.          write(Work_Line^.Valu_Line);
  333.       end else
  334.       begin
  335.          GotoXY(1,succ(CursorLine));
  336.          InsLine;
  337.          write(Work_Line^.Valu_Line);
  338.       end;
  339.    end
  340.    else
  341.    begin
  342.       if Active_Line-Screen_Top >= Lines_Avail then
  343.       begin
  344.          GoToXY(1,1);
  345.          DelLine;
  346.          inc(Screen_Top);
  347.       end;
  348.       if not Find_Line(succ(Active_Line)) then
  349.       Work_Line := Get_Line_Mem(Edit_Lgth);
  350.       GotoXY(1,CursorLine);
  351.       write(Work_Line^.Valu_Line);
  352.    end;
  353.    CursorPos := 1;
  354. end;
  355.  
  356. procedure GS_Edit_Objt.Pressed_CrtlY;
  357. var
  358.    p : GS_Edit_Pntr;
  359. begin
  360.    if Total_Lines <= 1 then
  361.    begin
  362.       if not Find_Line(1) then
  363.       begin
  364.          SoundBell(BeepTime,BeepFreq);
  365.          ShowError(750,'Lost track of edit line');
  366.          exit;
  367.       end;
  368.       Work_Line^.Valu_Line := '';
  369.       DelLine;
  370.       exit;
  371.    end;
  372.    Rel_Line_Mem(Active_Line);
  373.    DelLine;
  374.    p := Work_Line;
  375.    CursorLine := succ(Active_Line-Screen_Top);
  376.    if length(Work_Line^.Valu_Line)+1 < CursorPos then
  377.       CursorPos := length(Work_Line^.Valu_Line)+1;
  378.    Show_Lines(Screen_Top,Total_Lines);
  379. end;
  380.  
  381.  
  382. procedure GS_Edit_Objt.Check_Func_Keys;
  383. var
  384.    i : integer;
  385. begin
  386.    case Ch_Work of
  387.             Kbd_F1    : Pressed_F1;
  388.             Kbd_Home  : CursorPos := 1;
  389.             Kbd_End   : CursorPos := Succ(Length(Work_Line^.Valu_Line));
  390.             Kbd_Ins   : begin
  391.                            GS_KeyI_Ins := not GS_KeyI_Ins;
  392.                            GS_Scrn_SetCursor(GS_KeyI_Ins);
  393.                         end;
  394.             Kbd_LfAr  : if CursorPos > 1 then Dec(CursorPos);
  395.             Kbd_RtAr  : if CursorPos <= Length(Work_Line^.Valu_Line) then Inc(CursorPos);
  396.             Kbd_Bsp   : Pressed_Bsp;
  397.             Kbd_Del   : Pressed_Del;
  398.             Kbd_PgUp  : Pressed_PgUp;
  399.             Kbd_PgDn  : Pressed_PgDn;
  400.             Kbd_UpAr  : Pressed_UpAr;
  401.             Kbd_DnAr :  Pressed_DnAr;
  402.             Kbd_Ret   : Pressed_Ret;
  403.             Kbd_Esc   : GS_KeyI_Esc := True;
  404.             #25       : Pressed_CrtlY;  {CTRL-Y}
  405.  
  406.    end;
  407. end;
  408.  
  409. {
  410.          ┌──────────────────────────────────────────────────────────┐
  411.          │  ********        Edit String Procedure         *******   │
  412.          │                                                          │
  413.          │  This is the main method to edit an input string.  The   │
  414.          │  usual cursor keys are processed through a method that   │
  415.          │  may be replaced by a child object's virtual method.     │
  416.          │  The Escape key will terminate and return the default    │
  417.          │  value to the calling program.                           │
  418.          └──────────────────────────────────────────────────────────┘
  419. }
  420.  
  421.  
  422. Procedure GS_Edit_Objt.Edit_Line;
  423. var
  424.    t1 : string;
  425.    lc,
  426.    xl,
  427.    yl,
  428.    i  : integer;
  429. begin
  430.    if Work_Line = nil then
  431.       Work_Line := Get_Line_Mem(Edit_Lgth);
  432.    Insert(Ch_Work, Work_Line^.Valu_Line, CursorPos);
  433.    Inc(CursorPos);                {Step to the next location in the string}
  434.    if not GS_KeyI_Ins then delete(Work_Line^.Valu_Line, CursorPos, 1);
  435.    GoToXY(1, CursorLine);
  436.    Write(Work_Line^.Valu_Line);
  437.    if length(Work_Line^.Valu_Line) >= Edit_Lgth then
  438.       WordWrap(Work_Line^.Valu_Line);
  439. end; { Edit_Line }
  440.  
  441. procedure GS_Edit_Objt.Edit;
  442. var
  443.    stx : string;
  444. begin
  445.    StatWin.SetWin;
  446.    write(' F1 for Help    CTRL-END to Quit    ESC to Abort');
  447.    EditWin.SetWin;
  448.    WW_Flag := false;
  449.    Screen_Top := 0;
  450.    Screen_Btm := 0;
  451.    Ch_Work := #0;
  452.    CursorPos := 1;
  453.    CursorLine := 1;
  454.    Temp_Line := '';
  455.    GS_KeyI_Ins := True;               {Start in insert mode}
  456.    GS_KeyI_Esc := False;              {Set the Escape flag false}
  457.    GS_KeyI_Ret := false;              {Set Return flag false}
  458.    Cursor_LocX := WhereX;
  459.    Cursor_LocY := WhereY;
  460.    Lines_Avail := hi(WindMax) - hi(WindMin);
  461.    inc(Lines_Avail);                  {Adjust for correct number}
  462.    GS_Scrn_SetCursor(GS_KeyI_Ins);    {Go set cursor size}
  463.    if First_Line = nil then
  464.       Work_Line := Get_Line_Mem(Edit_Lgth)
  465.    else
  466.    begin
  467.       Work_Line := First_Line;
  468.       Active_Line := 1;
  469.    end;
  470.    Show_Lines(1,Lines_Avail);
  471.    repeat
  472.       window(1,24,80,24);
  473.       gotoxy(55,1);
  474.       write('Col: ',CursorPos:2,'   Line: ',Active_Line,'':4);
  475.       window(EditWin.X1,EditWin.Y1,EditWin.X2,EditWin.Y2);
  476.       CursorLine := succ(Active_Line-Screen_Top);
  477.       GotoXY(CursorPos, CursorLine);  {Go to current position in the screen}
  478.                                       {write updated part of line}
  479.       Ch_Work := GS_KeyI_GetKey;      {Get the next keyboard entry}
  480.       if (GS_KeyI_Fuc) or (Ch_Work in [#0..#31]) then
  481.                                       {See if function key or control char}
  482.          Check_Func_Keys              {If it is, go process it.}
  483.       else                            {Otherwise add character to the string}
  484.          Edit_Line;                   {Go add character to the line}
  485.    until ((GS_KeyI_Chr = Kbd_CEnd) and
  486.          (GS_KeyI_Fuc)) or (GS_KeyI_Esc);
  487.                                       {Continue until Ctrl-End or Esc pressed}
  488.    GS_Scrn_SetCursor(False);          {Set cursor size to small cursor}
  489.    GS_KeyI_Ins := False;
  490.    EditWin.RelWin;
  491.    StatWin.RelWin;
  492. end;
  493.  
  494.  
  495. procedure GS_Edit_Objt.View;
  496. var
  497.    stx : string;
  498. begin
  499.    StatWin.SetWin;
  500.    write('ESC When Done':45);
  501.    EditWin.SetWin;
  502.    WW_Flag := false;
  503.    Screen_Top := 0;
  504.    Screen_Btm := 0;
  505.    Ch_Work := #0;
  506.    CursorPos := 1;
  507.    CursorLine := 1;
  508.    Temp_Line := '';
  509.    GS_KeyI_Ins := True;               {Start in insert mode}
  510.    GS_KeyI_Esc := False;              {Set the Escape flag false}
  511.    GS_KeyI_Ret := false;              {Set Return flag false}
  512.    Cursor_LocX := WhereX;
  513.    Cursor_LocY := WhereY;
  514.    Lines_Avail := hi(WindMax) - hi(WindMin);
  515.    inc(Lines_Avail);                  {Adjust for correct number}
  516.    if First_Line = nil then
  517.       Work_Line := Get_Line_Mem(Edit_Lgth)
  518.    else
  519.    begin
  520.       Work_Line := First_Line;
  521.       Active_Line := 1;
  522.    end;
  523.    Show_Lines(1,Lines_Avail);
  524.    repeat
  525.       Ch_Work := GS_KeyI_GetKey;      {Get the next keyboard entry}
  526.       if (GS_KeyI_Fuc) or (Ch_Work in [#0..#31]) then
  527.       case Ch_Work of
  528.          Kbd_PgUp : Pressed_PgUp;
  529.          Kbd_PgDn : Pressed_PgDn;
  530.       end;
  531.    until (Ch_Work = Kbd_Esc);
  532.                                       {Continue until Ctrl-End or Esc pressed}
  533.    GS_KeyI_Ins := False;
  534.    EditWin.RelWin;
  535.    StatWin.RelWin;
  536. end;
  537.  
  538. function GS_Edit_Objt.Find_Line(linenum : integer) : boolean;
  539. var
  540.    i : integer;
  541. begin
  542.    if linenum > Total_Lines then
  543.    begin
  544.       Find_Line := false;
  545.       exit;
  546.    end;
  547.    if First_Line = nil then Work_Line := nil
  548.    else
  549.    begin
  550.       Work_Line := First_Line;
  551.       i := 1;
  552.       while (i < linenum) and (Work_Line <> nil) do
  553.       begin
  554.          Work_Line := Work_Line^.Next_Line;
  555.          inc(i);
  556.       end;
  557.    end;
  558.    if Work_Line = nil then
  559.    begin
  560.       Find_line := false;
  561.       ShowError(710,'Find_Line');
  562.    end
  563.    else
  564.    begin
  565.       Find_Line := true;
  566.       Active_Line := linenum;
  567.    end;
  568. end;
  569.  
  570.  
  571. function GS_Edit_Objt.Get_Line_Mem(lth : integer) : pointer;
  572. var
  573.    i : longint;
  574.    p : GS_Edit_Pntr;
  575. begin
  576.    GetMem(Work_Line,lth+15);
  577.    if First_Line = nil then
  578.    begin
  579.       First_Line := Work_Line;
  580.       End_Line := Work_Line;
  581.       Work_Line^.Next_Line := nil;
  582.       Work_Line^.Prev_Line := nil;
  583.       Active_Line := 1;
  584.    end else
  585.    begin
  586.       p := First_Line;
  587.       i := 1;
  588.       while (i < Active_Line) and (p^.Next_Line <> nil) do
  589.       begin
  590.          p := p^.Next_Line;
  591.          inc(i);
  592.       end;
  593.       Work_Line^.Next_Line := p^.Next_Line;
  594.       p^.Next_Line := Work_Line;
  595.       Work_Line^.Prev_Line := p;
  596.       Work_Line^.Next_Line^.Prev_Line := Work_Line;
  597.       inc(Active_Line);
  598.    end;
  599.    Work_Line^.Return_Cod := $0D;
  600.    Work_Line^.Line_Size := lth+15;
  601.    Work_Line^.Valu_Line := '';
  602.    inc(Total_Lines);
  603.    Get_Line_Mem := Work_Line;
  604. end;
  605.  
  606. Procedure GS_Edit_Objt.Rel_Line_Mem(linenum : integer);
  607. var
  608.    wl : GS_Edit_Pntr;
  609. begin
  610.    if First_Line = nil then exit;
  611.    if not Find_Line(linenum) then exit;
  612.    if Work_Line = First_Line then
  613.    begin
  614.       First_Line := Work_Line^.Next_Line;
  615.       if First_Line <> nil then First_Line^.Prev_Line := nil;
  616.    end
  617.    else
  618.    begin
  619.       wl := Work_Line^.Prev_Line;
  620.       Work_Line^.Prev_Line^.Next_Line := Work_Line^.Next_Line;
  621.       if Work_Line^.Next_Line <> nil then
  622.          Work_Line^.Next_Line^.Prev_Line := Work_Line^.Prev_Line;
  623.    end;
  624.    FreeMem(Work_Line,Work_Line^.Line_Size);
  625.    dec(Total_Lines);
  626.    if Total_Lines < Active_Line then Active_Line := Total_Lines;
  627.    if not Find_line(Active_Line) then ShowError(710,'Rel_Line_Mem');
  628. end;
  629.  
  630. Procedure GS_Edit_Objt.Show_Lines(b, e : integer);
  631. var
  632.    i,
  633.    j : integer;
  634.    p : pointer;
  635.    a : longint;
  636. begin;
  637.    if First_Line = nil then exit;
  638.    p := Work_Line;
  639.    a := Active_Line;
  640.    if b > Total_Lines then b := Total_Lines;
  641.    if e > Total_Lines then e := Total_Lines;
  642.    if e >= b + Lines_Avail then e := pred(b+Lines_Avail);
  643.    if not Find_Line(b) then
  644.    begin
  645.       ShowError(710,'Show_Lines');
  646.       Work_Line := p;
  647.       Active_Line := a;
  648.       exit;
  649.    end;
  650.    Screen_Top := b;
  651.    j := 1;
  652.    ClrScr;
  653.    for i := b to e do
  654.    begin
  655.       gotoxy(1,j);
  656.       inc(j);
  657.       write(Work_Line^.Valu_Line);
  658.       ClrEol;
  659.       Work_Line := Work_Line^.Next_Line;
  660.    end;
  661.    Work_Line := p;
  662.    Active_Line := a;
  663. end;
  664.  
  665.  
  666. Procedure GS_Edit_Objt.WordWrap(Fline : string);
  667. var
  668.    lCnt : integer;                    {Counter for line length in characters}
  669.    linterm : byte;                    {Holds line termination code}
  670.    linchr : boolean;
  671.    wrapped : boolean;
  672.    A_L    : longint;
  673.    wLine  : string;
  674.  
  675.  
  676.    function WrapLine : boolean;
  677.    BEGIN                       { WordWrap }
  678.       if (length(wline) <= Edit_Lgth) then
  679.       begin
  680.          WrapLine := false;
  681.          exit;
  682.       end;
  683.       WrapLine := true;
  684.       lCnt := Edit_Lgth+1;
  685.       linchr := false;
  686.       while (not linchr) and (lcnt > 0) do
  687.       begin
  688.          case wline[lCnt] of
  689.             ' '  :  linchr := true;
  690.             '-'  :  linchr := true;
  691.             else    dec(lCnt);
  692.          end;
  693.                                       {Repeat search for space or hyphen until}
  694.                                       {found or current line exhausted}
  695.       end;
  696.       if (lCnt = 0) then lcnt := Edit_Lgth;
  697.                                       {If no break point, truncate line}
  698.       Temp_Line := wline;
  699.       delete(Temp_Line,1,lCnt);
  700.       wline[0] := chr(lcnt);
  701.                                       {Get string up to cursor to split line}
  702.       if (CursorPos < length(wline)) and
  703.          ((Temp_Line = ' ') or (Temp_Line = '')) then
  704.       begin
  705.          WrapLine := false;
  706.          exit;
  707.       end;
  708.    end;
  709.  
  710. BEGIN
  711.    wrapped := false;
  712.    wline := Fline;
  713.    A_L := Active_Line;
  714.    while WrapLine do
  715.    begin
  716.       wrapped := true;
  717.       Work_Line^.Valu_Line := wline;
  718.       linterm := Work_Line^.Return_Cod;
  719.       Work_Line^.Return_Cod := $8D;   {Insert soft return character}
  720.       if linterm = $0D then
  721.       begin
  722.          Work_Line := Get_Line_Mem(Edit_Lgth);
  723.          Work_Line^.Return_Cod := linterm;
  724.       end
  725.       else
  726.       begin
  727.          if not Find_Line(succ(Active_Line)) then
  728.          begin
  729.             Work_Line := Get_Line_Mem(Edit_Lgth);
  730.             Work_Line^.Return_Cod := linterm;
  731.          end;
  732.       end;
  733.       wline := Temp_Line + Work_Line^.Valu_Line;
  734.    end;
  735.    Work_Line^.Valu_Line := wline;
  736.    if not wrapped then exit;
  737.    if not Find_Line(A_L) then
  738.    begin
  739.       ShowError(710,'WordWrap');
  740.    end;
  741.    if (CursorPos > length(Work_Line^.Valu_Line)) and
  742.       (CursorPos <> Edit_Lgth+1) then
  743.    begin
  744.       CursorPos := CursorPos - length(Work_Line^.Valu_Line);
  745.       if not Find_Line(succ(Active_Line)) then
  746.       begin
  747.          ShowError(710,'WordWrap 2');
  748.       end;
  749.    end;
  750.    if ((succ(Active_Line)) - Screen_Top) > Lines_Avail then
  751.    begin
  752.       Screen_Top := (succ(Active_Line)) - Lines_Avail;
  753.    end;
  754.    Show_Lines(Screen_Top, (Screen_Top-1) + Lines_Avail);
  755.    CursorLine := (succ(Active_Line)) - Screen_Top;
  756. end;                         {WordWrap}
  757.  
  758. begin
  759.    StatWin.InitWin(1,23,80,25,Yellow,Black,LightGray,Black,LightGray,
  760.                    true,'',true);
  761.    EditWin.InitWin(1,1,80,22,LightGray,Black,LightGray,Black,LightGray,
  762.                    false,'',true);
  763.    HelpWin.InitWin(29,2,51,20,Yellow,Black,Yellow,Black,LightGray,
  764.                    true,'[ Edit Help ]',true);
  765. end.
  766.